using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;

namespace ICSharpCode.TextEditor.Document
{
	public class DefaultHighlightingStrategy : IHighlightingStrategyUsingRuleSets, IHighlightingStrategy
	{
		private string name;

		private List<HighlightRuleSet> rules = new List<HighlightRuleSet>();

		private Dictionary<string, HighlightColor> environmentColors = new Dictionary<string, HighlightColor>();

		private Dictionary<string, string> properties = new Dictionary<string, string>();

		private string[] extensions;

		private HighlightColor digitColor;

		private HighlightRuleSet defaultRuleSet = null;

		private HighlightColor defaultTextColor;

		protected LineSegment currentLine;

		protected int currentLineNumber;

		protected SpanStack currentSpanStack;

		protected bool inSpan;

		protected Span activeSpan;

		protected HighlightRuleSet activeRuleSet;

		protected int currentOffset;

		protected int currentLength;

		public HighlightColor DigitColor
		{
			get
			{
				return this.digitColor;
			}
			set
			{
				this.digitColor = value;
			}
		}

		public IEnumerable<KeyValuePair<string, HighlightColor>> EnvironmentColors => this.environmentColors;

		public Dictionary<string, string> Properties => this.properties;

		public string Name => this.name;

		public string[] Extensions
		{
			get
			{
				return this.extensions;
			}
			set
			{
				this.extensions = value;
			}
		}

		public List<HighlightRuleSet> Rules => this.rules;

		public HighlightColor DefaultTextColor => this.defaultTextColor;

		protected void ImportSettingsFrom(DefaultHighlightingStrategy source)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			this.properties = source.properties;
			this.extensions = source.extensions;
			this.digitColor = source.digitColor;
			this.defaultRuleSet = source.defaultRuleSet;
			this.name = source.name;
			this.rules = source.rules;
			this.environmentColors = source.environmentColors;
			this.defaultTextColor = source.defaultTextColor;
		}

		public DefaultHighlightingStrategy()
			: this("Default")
		{
		}

		public DefaultHighlightingStrategy(string name)
		{
			this.name = name;
			this.digitColor = new HighlightColor(SystemColors.WindowText, bold: false, italic: false);
			this.defaultTextColor = new HighlightColor(SystemColors.WindowText, bold: false, italic: false);
			this.environmentColors["Default"] = new HighlightBackground("WindowText", "Window", bold: false, italic: false);
			this.environmentColors["Selection"] = new HighlightColor("HighlightText", "Highlight", bold: false, italic: false);
			this.environmentColors["VRuler"] = new HighlightColor("ControlLight", "Window", bold: false, italic: false);
			this.environmentColors["InvalidLines"] = new HighlightColor(Color.Red, bold: false, italic: false);
			this.environmentColors["CaretMarker"] = new HighlightColor(Color.Yellow, bold: false, italic: false);
			this.environmentColors["CaretLine"] = new HighlightBackground("ControlLight", "Window", bold: false, italic: false);
			this.environmentColors["LineNumbers"] = new HighlightBackground("ControlDark", "Window", bold: false, italic: false);
			this.environmentColors["FoldLine"] = new HighlightColor("ControlDark", bold: false, italic: false);
			this.environmentColors["FoldMarker"] = new HighlightColor("WindowText", "Window", bold: false, italic: false);
			this.environmentColors["SelectedFoldLine"] = new HighlightColor("WindowText", bold: false, italic: false);
			this.environmentColors["EOLMarkers"] = new HighlightColor("ControlLight", "Window", bold: false, italic: false);
			this.environmentColors["SpaceMarkers"] = new HighlightColor("ControlLight", "Window", bold: false, italic: false);
			this.environmentColors["TabMarkers"] = new HighlightColor("ControlLight", "Window", bold: false, italic: false);
		}

		public HighlightRuleSet FindHighlightRuleSet(string name)
		{
			foreach (HighlightRuleSet rule in this.rules)
			{
				if (rule.Name == name)
				{
					return rule;
				}
			}
			return null;
		}

		public void AddRuleSet(HighlightRuleSet aRuleSet)
		{
			HighlightRuleSet highlightRuleSet = this.FindHighlightRuleSet(aRuleSet.Name);
			if (highlightRuleSet != null)
			{
				highlightRuleSet.MergeFrom(aRuleSet);
			}
			else
			{
				this.rules.Add(aRuleSet);
			}
		}

		public void ResolveReferences()
		{
			this.ResolveRuleSetReferences();
			this.ResolveExternalReferences();
		}

		private void ResolveRuleSetReferences()
		{
			foreach (HighlightRuleSet rule in this.Rules)
			{
				if (rule.Name == null)
				{
					this.defaultRuleSet = rule;
				}
				foreach (Span span in rule.Spans)
				{
					if (span.Rule != null)
					{
						bool flag = false;
						foreach (HighlightRuleSet rule2 in this.Rules)
						{
							if (rule2.Name == span.Rule)
							{
								flag = true;
								span.RuleSet = rule2;
								break;
							}
						}
						if (!flag)
						{
							span.RuleSet = null;
							throw new HighlightingDefinitionInvalidException("The RuleSet " + span.Rule + " could not be found in mode definition " + this.Name);
						}
					}
					else
					{
						span.RuleSet = null;
					}
				}
			}
			if (this.defaultRuleSet == null)
			{
				throw new HighlightingDefinitionInvalidException("No default RuleSet is defined for mode definition " + this.Name);
			}
		}

		private void ResolveExternalReferences()
		{
			foreach (HighlightRuleSet rule in this.Rules)
			{
				rule.Highlighter = this;
				if (rule.Reference != null)
				{
					IHighlightingStrategy highlightingStrategy = HighlightingManager.Manager.FindHighlighter(rule.Reference);
					if (highlightingStrategy == null)
					{
						throw new HighlightingDefinitionInvalidException("The mode defintion " + rule.Reference + " which is refered from the " + this.Name + " mode definition could not be found");
					}
					if (!(highlightingStrategy is IHighlightingStrategyUsingRuleSets))
					{
						throw new HighlightingDefinitionInvalidException("The mode defintion " + rule.Reference + " which is refered from the " + this.Name + " mode definition does not implement IHighlightingStrategyUsingRuleSets");
					}
					rule.Highlighter = (IHighlightingStrategyUsingRuleSets)highlightingStrategy;
				}
			}
		}

		public void SetColorFor(string name, HighlightColor color)
		{
			if (name == "Default")
			{
				this.defaultTextColor = new HighlightColor(color.Color, color.Bold, color.Italic);
			}
			this.environmentColors[name] = color;
		}

		public HighlightColor GetColorFor(string name)
		{
			if (this.environmentColors.TryGetValue(name, out var value))
			{
				return value;
			}
			return this.defaultTextColor;
		}

		public HighlightColor GetColor(IDocument document, LineSegment currentSegment, int currentOffset, int currentLength)
		{
			return this.GetColor(this.defaultRuleSet, document, currentSegment, currentOffset, currentLength);
		}

		protected virtual HighlightColor GetColor(HighlightRuleSet ruleSet, IDocument document, LineSegment currentSegment, int currentOffset, int currentLength)
		{
			if (ruleSet != null)
			{
				if (ruleSet.Reference != null)
				{
					return ruleSet.Highlighter.GetColor(document, currentSegment, currentOffset, currentLength);
				}
				return (HighlightColor)ruleSet.KeyWords[document, currentSegment, currentOffset, currentLength];
			}
			return null;
		}

		public HighlightRuleSet GetRuleSet(Span aSpan)
		{
			if (aSpan == null)
			{
				return this.defaultRuleSet;
			}
			if (aSpan.RuleSet != null)
			{
				if (aSpan.RuleSet.Reference != null)
				{
					return aSpan.RuleSet.Highlighter.GetRuleSet(null);
				}
				return aSpan.RuleSet;
			}
			return null;
		}

		public virtual void MarkTokens(IDocument document)
		{
			if (this.Rules.Count == 0)
			{
				return;
			}
			for (int i = 0; i < document.TotalNumberOfLines; i++)
			{
				LineSegment lineSegment = ((i > 0) ? document.GetLineSegment(i - 1) : null);
				if (i >= document.LineSegmentCollection.Count)
				{
					break;
				}
				this.currentSpanStack = ((lineSegment != null && lineSegment.HighlightSpanStack != null) ? lineSegment.HighlightSpanStack.Clone() : null);
				if (this.currentSpanStack != null)
				{
					while (!this.currentSpanStack.IsEmpty && this.currentSpanStack.Peek().StopEOL)
					{
						this.currentSpanStack.Pop();
					}
					if (this.currentSpanStack.IsEmpty)
					{
						this.currentSpanStack = null;
					}
				}
				this.currentLine = document.LineSegmentCollection[i];
				if (this.currentLine.Length == -1)
				{
					return;
				}
				this.currentLineNumber = i;
				List<TextWord> words = this.ParseLine(document);
				if (this.currentLine.Words != null)
				{
					this.currentLine.Words.Clear();
				}
				this.currentLine.Words = words;
				this.currentLine.HighlightSpanStack = ((this.currentSpanStack == null || this.currentSpanStack.IsEmpty) ? null : this.currentSpanStack);
			}
			document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.WholeTextArea));
			document.CommitUpdate();
			this.currentLine = null;
		}

		private bool MarkTokensInLine(IDocument document, int lineNumber, ref bool spanChanged)
		{
			this.currentLineNumber = lineNumber;
			bool result = false;
			LineSegment lineSegment = ((lineNumber > 0) ? document.GetLineSegment(lineNumber - 1) : null);
			this.currentSpanStack = ((lineSegment != null && lineSegment.HighlightSpanStack != null) ? lineSegment.HighlightSpanStack.Clone() : null);
			if (this.currentSpanStack != null)
			{
				while (!this.currentSpanStack.IsEmpty && this.currentSpanStack.Peek().StopEOL)
				{
					this.currentSpanStack.Pop();
				}
				if (this.currentSpanStack.IsEmpty)
				{
					this.currentSpanStack = null;
				}
			}
			this.currentLine = document.LineSegmentCollection[lineNumber];
			if (this.currentLine.Length == -1)
			{
				return false;
			}
			List<TextWord> words = this.ParseLine(document);
			if (this.currentSpanStack != null && this.currentSpanStack.IsEmpty)
			{
				this.currentSpanStack = null;
			}
			if (this.currentLine.HighlightSpanStack != this.currentSpanStack)
			{
				if (this.currentLine.HighlightSpanStack == null)
				{
					result = false;
					foreach (Span item in this.currentSpanStack)
					{
						if (!item.StopEOL)
						{
							spanChanged = true;
							result = true;
							break;
						}
					}
				}
				else if (this.currentSpanStack == null)
				{
					result = false;
					foreach (Span item2 in this.currentLine.HighlightSpanStack)
					{
						if (!item2.StopEOL)
						{
							spanChanged = true;
							result = true;
							break;
						}
					}
				}
				else
				{
					SpanStack.Enumerator enumerator3 = this.currentSpanStack.GetEnumerator();
					SpanStack.Enumerator enumerator4 = this.currentLine.HighlightSpanStack.GetEnumerator();
					bool flag = false;
					while (!flag)
					{
						bool flag2 = false;
						while (enumerator3.MoveNext())
						{
							if (!enumerator3.Current.StopEOL)
							{
								flag2 = true;
								break;
							}
						}
						bool flag3 = false;
						while (enumerator4.MoveNext())
						{
							if (!enumerator4.Current.StopEOL)
							{
								flag3 = true;
								break;
							}
						}
						if (flag2 || flag3)
						{
							if (flag2 && flag3)
							{
								if (enumerator3.Current != enumerator4.Current)
								{
									flag = true;
									result = true;
									spanChanged = true;
								}
							}
							else
							{
								spanChanged = true;
								flag = true;
								result = true;
							}
						}
						else
						{
							flag = true;
							result = false;
						}
					}
				}
			}
			else
			{
				result = false;
			}
			if (this.currentLine.Words != null)
			{
				this.currentLine.Words.Clear();
			}
			this.currentLine.Words = words;
			this.currentLine.HighlightSpanStack = ((this.currentSpanStack != null && !this.currentSpanStack.IsEmpty) ? this.currentSpanStack : null);
			return result;
		}

		public virtual void MarkTokens(IDocument document, List<LineSegment> inputLines)
		{
			if (this.Rules.Count == 0)
			{
				return;
			}
			Dictionary<LineSegment, bool> dictionary = new Dictionary<LineSegment, bool>();
			bool spanChanged = false;
			int count = document.LineSegmentCollection.Count;
			foreach (LineSegment inputLine in inputLines)
			{
				if (dictionary.ContainsKey(inputLine))
				{
					continue;
				}
				int num = inputLine.LineNumber;
				bool flag = true;
				if (num != -1)
				{
					while (flag && num < count)
					{
						flag = this.MarkTokensInLine(document, num, ref spanChanged);
						dictionary[this.currentLine] = true;
						num++;
					}
				}
			}
			if (spanChanged || inputLines.Count > 20)
			{
				document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.WholeTextArea));
			}
			else
			{
				foreach (LineSegment inputLine2 in inputLines)
				{
					document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, inputLine2.LineNumber));
				}
			}
			document.CommitUpdate();
			this.currentLine = null;
		}

		private void UpdateSpanStateVariables()
		{
			this.inSpan = this.currentSpanStack != null && !this.currentSpanStack.IsEmpty;
			this.activeSpan = (this.inSpan ? this.currentSpanStack.Peek() : null);
			this.activeRuleSet = this.GetRuleSet(this.activeSpan);
		}

		private List<TextWord> ParseLine(IDocument document)
		{
			List<TextWord> list = new List<TextWord>();
			HighlightColor markNext = null;
			this.currentOffset = 0;
			this.currentLength = 0;
			this.UpdateSpanStateVariables();
			int length = this.currentLine.Length;
			int offset = this.currentLine.Offset;
			for (int i = 0; i < length; i++)
			{
				char charAt = document.GetCharAt(offset + i);
				switch (charAt)
				{
				case '\n':
				case '\r':
					this.PushCurWord(document, ref markNext, list);
					this.currentOffset++;
					continue;
				case ' ':
					this.PushCurWord(document, ref markNext, list);
					if (this.activeSpan != null && this.activeSpan.Color.HasBackground)
					{
						list.Add(new TextWord.SpaceTextWord(this.activeSpan.Color));
					}
					else
					{
						list.Add(TextWord.Space);
					}
					this.currentOffset++;
					continue;
				case '\t':
					this.PushCurWord(document, ref markNext, list);
					if (this.activeSpan != null && this.activeSpan.Color.HasBackground)
					{
						list.Add(new TextWord.TabTextWord(this.activeSpan.Color));
					}
					else
					{
						list.Add(TextWord.Tab);
					}
					this.currentOffset++;
					continue;
				}
				char c = '\0';
				if (this.activeSpan != null && this.activeSpan.EscapeCharacter != 0)
				{
					c = this.activeSpan.EscapeCharacter;
				}
				else if (this.activeRuleSet != null)
				{
					c = this.activeRuleSet.EscapeCharacter;
				}
				if (c != 0 && c == charAt)
				{
					if (this.activeSpan == null || this.activeSpan.End == null || this.activeSpan.End.Length != 1 || c != this.activeSpan.End[0])
					{
						this.currentLength++;
						if (i + 1 < length)
						{
							this.currentLength++;
						}
						this.PushCurWord(document, ref markNext, list);
						i++;
						continue;
					}
					if (i + 1 < length && document.GetCharAt(offset + i + 1) == c)
					{
						this.currentLength += 2;
						this.PushCurWord(document, ref markNext, list);
						i++;
						continue;
					}
				}
				if (!this.inSpan && (char.IsDigit(charAt) || (charAt == '.' && i + 1 < length && char.IsDigit(document.GetCharAt(offset + i + 1)))) && this.currentLength == 0)
				{
					bool flag = false;
					bool flag2 = false;
					if (charAt == '0' && i + 1 < length && char.ToUpper(document.GetCharAt(offset + i + 1)) == 'X')
					{
						this.currentLength++;
						i++;
						this.currentLength++;
						flag = true;
						while (i + 1 < length && "0123456789ABCDEF".IndexOf(char.ToUpper(document.GetCharAt(offset + i + 1))) != -1)
						{
							i++;
							this.currentLength++;
						}
					}
					else
					{
						this.currentLength++;
						while (i + 1 < length && char.IsDigit(document.GetCharAt(offset + i + 1)))
						{
							i++;
							this.currentLength++;
						}
					}
					if (!flag && i + 1 < length && document.GetCharAt(offset + i + 1) == '.')
					{
						flag2 = true;
						i++;
						this.currentLength++;
						while (i + 1 < length && char.IsDigit(document.GetCharAt(offset + i + 1)))
						{
							i++;
							this.currentLength++;
						}
					}
					if (i + 1 < length && char.ToUpper(document.GetCharAt(offset + i + 1)) == 'E')
					{
						flag2 = true;
						i++;
						this.currentLength++;
						if (i + 1 < length && (document.GetCharAt(offset + i + 1) == '+' || document.GetCharAt(this.currentLine.Offset + i + 1) == '-'))
						{
							i++;
							this.currentLength++;
						}
						while (i + 1 < this.currentLine.Length && char.IsDigit(document.GetCharAt(offset + i + 1)))
						{
							i++;
							this.currentLength++;
						}
					}
					if (i + 1 < this.currentLine.Length)
					{
						char c2 = char.ToUpper(document.GetCharAt(offset + i + 1));
						if (c2 == 'F' || c2 == 'M' || c2 == 'D')
						{
							flag2 = true;
							i++;
							this.currentLength++;
						}
					}
					if (!flag2)
					{
						bool flag3 = false;
						if (i + 1 < length && char.ToUpper(document.GetCharAt(offset + i + 1)) == 'U')
						{
							i++;
							this.currentLength++;
							flag3 = true;
						}
						if (i + 1 < length && char.ToUpper(document.GetCharAt(offset + i + 1)) == 'L')
						{
							i++;
							this.currentLength++;
							if (!flag3 && i + 1 < length && char.ToUpper(document.GetCharAt(offset + i + 1)) == 'U')
							{
								i++;
								this.currentLength++;
							}
						}
					}
					list.Add(new TextWord(document, this.currentLine, this.currentOffset, this.currentLength, this.DigitColor, hasDefaultColor: false));
					this.currentOffset += this.currentLength;
					this.currentLength = 0;
					continue;
				}
				if (this.inSpan && this.activeSpan.End != null && this.activeSpan.End.Length != 0 && DefaultHighlightingStrategy.MatchExpr(this.currentLine, this.activeSpan.End, i, document, this.activeSpan.IgnoreCase))
				{
					this.PushCurWord(document, ref markNext, list);
					string regString = DefaultHighlightingStrategy.GetRegString(this.currentLine, this.activeSpan.End, i, document);
					this.currentLength += regString.Length;
					list.Add(new TextWord(document, this.currentLine, this.currentOffset, this.currentLength, this.activeSpan.EndColor, hasDefaultColor: false));
					this.currentOffset += this.currentLength;
					this.currentLength = 0;
					i += regString.Length - 1;
					this.currentSpanStack.Pop();
					this.UpdateSpanStateVariables();
					continue;
				}
				if (this.activeRuleSet != null)
				{
					foreach (Span span in this.activeRuleSet.Spans)
					{
						if ((span.IsBeginSingleWord && this.currentLength != 0) || (span.IsBeginStartOfLine.HasValue && span.IsBeginStartOfLine.Value != (this.currentLength == 0 && list.TrueForAll((TextWord textWord) => textWord.Type != TextWordType.Word))) || !DefaultHighlightingStrategy.MatchExpr(this.currentLine, span.Begin, i, document, this.activeRuleSet.IgnoreCase))
						{
							continue;
						}
						this.PushCurWord(document, ref markNext, list);
						string regString2 = DefaultHighlightingStrategy.GetRegString(this.currentLine, span.Begin, i, document);
						if (!this.OverrideSpan(regString2, document, list, span, ref i))
						{
							this.currentLength += regString2.Length;
							list.Add(new TextWord(document, this.currentLine, this.currentOffset, this.currentLength, span.BeginColor, hasDefaultColor: false));
							this.currentOffset += this.currentLength;
							this.currentLength = 0;
							i += regString2.Length - 1;
							if (this.currentSpanStack == null)
							{
								this.currentSpanStack = new SpanStack();
							}
							this.currentSpanStack.Push(span);
							span.IgnoreCase = this.activeRuleSet.IgnoreCase;
							this.UpdateSpanStateVariables();
						}
						goto IL_0a04;
					}
				}
				if (this.activeRuleSet != null && charAt < 'Ā' && this.activeRuleSet.Delimiters[(uint)charAt])
				{
					this.PushCurWord(document, ref markNext, list);
					if (this.currentOffset + this.currentLength + 1 < this.currentLine.Length)
					{
						this.currentLength++;
						this.PushCurWord(document, ref markNext, list);
						continue;
					}
				}
				this.currentLength++;
				IL_0a04:;
			}
			this.PushCurWord(document, ref markNext, list);
			this.OnParsedLine(document, this.currentLine, list);
			return list;
		}

		protected virtual void OnParsedLine(IDocument document, LineSegment currentLine, List<TextWord> words)
		{
		}

		protected virtual bool OverrideSpan(string spanBegin, IDocument document, List<TextWord> words, Span span, ref int lineOffset)
		{
			return false;
		}

		private void PushCurWord(IDocument document, ref HighlightColor markNext, List<TextWord> words)
		{
			if (this.currentLength <= 0)
			{
				return;
			}
			if (words.Count > 0 && this.activeRuleSet != null)
			{
				TextWord textWord = null;
				for (int num = words.Count - 1; num >= 0; num--)
				{
					if (!words[num].IsWhiteSpace)
					{
						textWord = words[num];
						if (textWord.HasDefaultColor)
						{
							PrevMarker prevMarker = (PrevMarker)this.activeRuleSet.PrevMarkers[document, this.currentLine, this.currentOffset, this.currentLength];
							if (prevMarker != null)
							{
								textWord.SyntaxColor = prevMarker.Color;
							}
						}
						break;
					}
				}
			}
			if (this.inSpan)
			{
				HighlightColor highlightColor = null;
				bool hasDefaultColor = true;
				if (this.activeSpan.Rule == null)
				{
					highlightColor = this.activeSpan.Color;
				}
				else
				{
					highlightColor = this.GetColor(this.activeRuleSet, document, this.currentLine, this.currentOffset, this.currentLength);
					hasDefaultColor = false;
				}
				if (highlightColor == null)
				{
					highlightColor = this.activeSpan.Color;
					if (highlightColor.Color == Color.Transparent)
					{
						highlightColor = this.DefaultTextColor;
					}
					hasDefaultColor = true;
				}
				words.Add(new TextWord(document, this.currentLine, this.currentOffset, this.currentLength, (markNext != null) ? markNext : highlightColor, hasDefaultColor));
			}
			else
			{
				HighlightColor highlightColor2 = ((markNext != null) ? markNext : this.GetColor(this.activeRuleSet, document, this.currentLine, this.currentOffset, this.currentLength));
				if (highlightColor2 == null)
				{
					words.Add(new TextWord(document, this.currentLine, this.currentOffset, this.currentLength, this.DefaultTextColor, hasDefaultColor: true));
				}
				else
				{
					words.Add(new TextWord(document, this.currentLine, this.currentOffset, this.currentLength, highlightColor2, hasDefaultColor: false));
				}
			}
			if (this.activeRuleSet != null)
			{
				NextMarker nextMarker = (NextMarker)this.activeRuleSet.NextMarkers[document, this.currentLine, this.currentOffset, this.currentLength];
				if (nextMarker != null)
				{
					if (nextMarker.MarkMarker && words.Count > 0)
					{
						TextWord textWord2 = words[words.Count - 1];
						textWord2.SyntaxColor = nextMarker.Color;
					}
					markNext = nextMarker.Color;
				}
				else
				{
					markNext = null;
				}
			}
			this.currentOffset += this.currentLength;
			this.currentLength = 0;
		}

		private static string GetRegString(LineSegment lineSegment, char[] expr, int index, IDocument document)
		{
			int num = 0;
			StringBuilder stringBuilder = new StringBuilder();
			int num2 = 0;
			while (num2 < expr.Length && index + num < lineSegment.Length)
			{
				char c = expr[num2];
				char c2 = c;
				if (c2 == '@')
				{
					num2++;
					if (num2 == expr.Length)
					{
						throw new HighlightingDefinitionInvalidException("Unexpected end of @ sequence, use @@ to look for a single @.");
					}
					switch (expr[num2])
					{
					case '!':
					{
						StringBuilder stringBuilder2 = new StringBuilder();
						num2++;
						while (num2 < expr.Length && expr[num2] != '@')
						{
							stringBuilder2.Append(expr[num2++]);
						}
						break;
					}
					case '@':
						stringBuilder.Append(document.GetCharAt(lineSegment.Offset + index + num));
						break;
					}
				}
				else
				{
					if (expr[num2] != document.GetCharAt(lineSegment.Offset + index + num))
					{
						return stringBuilder.ToString();
					}
					stringBuilder.Append(document.GetCharAt(lineSegment.Offset + index + num));
				}
				num2++;
				num++;
			}
			return stringBuilder.ToString();
		}

		private static bool MatchExpr(LineSegment lineSegment, char[] expr, int index, IDocument document, bool ignoreCase)
		{
			int num = 0;
			int num2 = 0;
			while (num < expr.Length)
			{
				char c = expr[num];
				char c2 = c;
				if (c2 == '@')
				{
					num++;
					if (num == expr.Length)
					{
						throw new HighlightingDefinitionInvalidException("Unexpected end of @ sequence, use @@ to look for a single @.");
					}
					switch (expr[num])
					{
					case 'C':
						if (index + num2 != lineSegment.Offset && index + num2 < lineSegment.Offset + lineSegment.Length)
						{
							char charAt = document.GetCharAt(lineSegment.Offset + index + num2);
							if (!char.IsWhiteSpace(charAt) && !char.IsPunctuation(charAt))
							{
								return false;
							}
						}
						break;
					case '!':
					{
						StringBuilder stringBuilder2 = new StringBuilder();
						num++;
						while (num < expr.Length && expr[num] != '@')
						{
							stringBuilder2.Append(expr[num++]);
						}
						if (lineSegment.Offset + index + num2 + stringBuilder2.Length >= document.TextLength)
						{
							break;
						}
						int j;
						for (j = 0; j < stringBuilder2.Length; j++)
						{
							char c5 = (ignoreCase ? char.ToUpperInvariant(document.GetCharAt(lineSegment.Offset + index + num2 + j)) : document.GetCharAt(lineSegment.Offset + index + num2 + j));
							char c6 = (ignoreCase ? char.ToUpperInvariant(stringBuilder2[j]) : stringBuilder2[j]);
							if (c5 != c6)
							{
								break;
							}
						}
						if (j >= stringBuilder2.Length)
						{
							return false;
						}
						break;
					}
					case '-':
					{
						StringBuilder stringBuilder = new StringBuilder();
						num++;
						while (num < expr.Length && expr[num] != '@')
						{
							stringBuilder.Append(expr[num++]);
						}
						if (index - stringBuilder.Length < 0)
						{
							break;
						}
						int i;
						for (i = 0; i < stringBuilder.Length; i++)
						{
							char c3 = (ignoreCase ? char.ToUpperInvariant(document.GetCharAt(lineSegment.Offset + index - stringBuilder.Length + i)) : document.GetCharAt(lineSegment.Offset + index - stringBuilder.Length + i));
							char c4 = (ignoreCase ? char.ToUpperInvariant(stringBuilder[i]) : stringBuilder[i]);
							if (c3 != c4)
							{
								break;
							}
						}
						if (i >= stringBuilder.Length)
						{
							return false;
						}
						break;
					}
					case '@':
						if (index + num2 >= lineSegment.Length || '@' != document.GetCharAt(lineSegment.Offset + index + num2))
						{
							return false;
						}
						break;
					}
				}
				else
				{
					if (index + num2 >= lineSegment.Length)
					{
						return false;
					}
					char c7 = (ignoreCase ? char.ToUpperInvariant(document.GetCharAt(lineSegment.Offset + index + num2)) : document.GetCharAt(lineSegment.Offset + index + num2));
					char c8 = (ignoreCase ? char.ToUpperInvariant(expr[num]) : expr[num]);
					if (c7 != c8)
					{
						return false;
					}
				}
				num++;
				num2++;
			}
			return true;
		}
	}
}
